//go:build windows
// +build windows

// Package ysos 目前只有 windows 的操作相关功能
package ysos

import (
	"bytes"
	"context"
	"fmt"
	"gitee.com/kmyss/gf-ex/yslog"
	"gitee.com/kmyss/gf-ex/ysutils"
	"github.com/gogf/gf/v2/encoding/gcharset"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gfile"
	"github.com/gogf/gf/v2/os/gproc"
	"github.com/gogf/gf/v2/text/gregex"
	"github.com/gogf/gf/v2/text/gstr"
	"os"
)

// OpenDir 利用资源管理器打开一个路径
func OpenDir(path string) {
	cmd := fmt.Sprintf(`%%SystemRoot%%\Explorer.exe %s`, gfile.Abs(path))
	yslog.Debug(cmd)
	_ = gproc.ShellRun(context.TODO(), cmd)
}

// CheckProcessByName 通过名称检查进程是否存在

func CheckProcessByName(name string) bool {
	cmd := "tasklist"
	buf := bytes.NewBuffer(nil)
	err := gproc.Shell(context.TODO(), cmd, buf, buf)
	if err != nil {
		yslog.Error(err)
		return false
	}
	utf8, err := gcharset.ToUTF8("gbk", buf.String())
	if err != nil {
		return false
	}

	for _, s := range gstr.Split(utf8, "\r\n") {
		if gregex.IsMatchString("^"+name, s) {
			return true
		}
	}
	return false
}

// KillProcessByName 通过完整的名称杀死一个进程
func KillProcessByName(name string) bool {
	cmd := fmt.Sprintf("taskkill /f /t /im %s", name)
	process := gproc.NewProcessCmd("")
	process.Args = append(process.Args, cmd)
	buf := bytes.NewBuffer(nil)
	process.Stdout = buf
	process.Stderr = buf
	err := process.Run(context.TODO())
	out, _ := gcharset.ToUTF8("gbk", buf.String())
	if err != nil {
		yslog.Error(out)
		return false
	}
	return true
}

// GetGitBashPath 找到 git 的准确路径
func GetGitBashPath(ctx context.Context) string {

	raw, err := gproc.ShellExec(ctx, "where git")
	if err != nil {
		return ""
	}
	yslog.Debug("git : ", raw)
	utf8, _ := gcharset.UTF8To("gbk", raw)
	gitPaths := gstr.SplitAndTrim(utf8, "\r\n")
	for _, gitPath := range gitPaths {
		gitDir := gfile.Join(gfile.Dir(gitPath), "..")
		tmp := ysutils.FindAbsFile(gitDir, "bash.exe")
		if !g.IsEmpty(tmp) {
			return tmp
		}
	}
	return ""
}

func HasCmd(ctx context.Context, cmd string) bool {
	_, err := gproc.ShellExec(ctx, "where "+cmd)
	if !g.IsNil(err) {
		return false
	}
	return true
}

// FindShExePath 搜索 sh 脚本可以运行的文件
func FindShExePath(ctx context.Context) string {
	gitBash := GetGitBashPath(ctx)
	if !g.IsEmpty(gitBash) {
		return gitBash
	}

	yslog.Warning("电脑内没有安装 git，尝试搜索 sh")

	if HasCmd(ctx, "sh") {
		return "sh"
	} else {
		return ysutils.FindFile(gfile.SelfDir()+","+gfile.Pwd(), "sh.exe")
	}

}

// RunShellFile 运行 sh 或者 bat 脚本
func RunShellFile(ctx context.Context, filePath string) error {
	cmd := ""
	if gstr.HasSuffix(filePath, ".bat") {
		cmd = gfile.Abs(filePath)
	} else if gstr.HasSuffix(filePath, ".sh") {
		path := FindShExePath(ctx)
		if g.IsEmpty(path) {
			return gerror.New("没有找到可执行 sh 脚本的程序")
		}

		if gstr.Contains(path, " ") {
			path = "\"" + path + "\""
		}
		cmd = path + " " + gstr.Replace(gstr.Replace(filePath, gfile.Pwd(), "."), "\\", "/")
	} else {
		return gerror.New("不支持运行的脚本类型")
	}
	yslog.Debug(cmd)
	return gproc.Shell(ctx, cmd, yslog.GetWriter(), os.Stdin)
}
